#!/usr/bin/env python
# -*- encoding=utf-8 -*-
'''
Created on 2017/12/28

@author: peulerosci
'''

import logging
import json, time
import logging.config
from subprocess import *
import os, re, sys, datetime
import tempfile
reload(sys)
sys.setdefaultencoding('utf8')

if not os.path.isdir("log"):
    os.mkdir("log")
logging.config.fileConfig("logger.conf")
logger = logging.getLogger("copy_jenkins")

if len(sys.argv) >= 4:
    BRANCH = sys.argv[2]
    PROJECT = sys.argv[3]
    CHANGE_ID = sys.argv[1]
    CHANGE_ID_1 = sys.argv[4]
else:
    BRANCH = os.getenv('GERRIT_BRANCH')
    PROJECT = os.getenv('GERRIT_PROJECT')
    CHANGE_ID = os.getenv('GERRIT_CHANGE_NUMBER')
    CHANGE_ID_1 = os.getenv('GERRIT_CHANGE_ID')
REPO_DIR = '/usr1/jenkins/EulerOS_' + BRANCH


def shell_cmd(s_cmd_line, inmsg=None):
    p = Popen(s_cmd_line, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
    if inmsg:
        p.stdin.write(inmsg)
    out, err = p.communicate()
    return p.returncode, out, err


def get_project_path():
    default_xml = REPO_DIR + '/.repo/manifest.xml'
    with open(default_xml, 'r') as myfile:
        mystr = myfile.read()
        tmppath = re.findall('<project path="(.+)"\s+name="{0}"'.format(PROJECT), mystr)
        if len(tmppath) == 1:
            mypath = tmppath[0]
            return mypath

        xml_list = re.findall(r'<include name="(.+)"/>', mystr)
        mypath = ''
        for next_xml in xml_list:
            with open(REPO_DIR + '/.repo/manifests/' + next_xml) as myxml:
                tmp_str = myxml.read()
                tmppath = re.findall('<project path="(.+)"\s+name="{0}"'.format(PROJECT), tmp_str)
                if len(tmppath) == 1:
                    mypath = tmppath[0]
                    #print '8888888888888============{0}'.format(mypath)
                    break
        if mypath == '':
            logger.error('can not find this git project: {0}'.format(PROJECT))
            sys.exit(1)

        return mypath


def check_spec_for_patch(project_dir, patch_list):
    # 根据changeid获取对应的commitid
    cmd = 'cd {0};git log --no-merges'.format(project_dir)
    ret, out, err = shell_cmd(cmd)
    if ret != 0:
        logger.error("run: %s : failed,the out is %s,the err is %s" % (cmd, out, err))
        sys.exit(1)
    commit_id = out.split(CHANGE_ID_1)[0].split('Change-Id:')[-2].split('Author:')[0].split('commit')[-1].split('\n')[0].replace('\r', '').replace(' ', '')

    # 切换到对应的提交点
    cmd = 'cd {0};git checkout {1}'.format(project_dir, commit_id)
    ret, out, err = shell_cmd(cmd)
    if ret != 0:
        logger.error("run: %s : failed,the out is %s,the err is %s" % (cmd, out, err))
        sys.exit(1)

    # 获取当前提交的spec的修改情况，如果没有spec的变更或changelog里面不是安全相关的就直接成功退出。如果是安全相关的就获取相关信息
    cmd = 'cd {0};git diff --name-status HEAD~1 HEAD~0'.format(project_dir)
    ret, out, err = shell_cmd(cmd)
    if ret != 0:
        logger.error("run: %s : failed,the out is %s,the err is %s" % (cmd, out, err))
        sys.exit(1)
    spec_list = re.findall('M\s(.+\.spec)', out)
    if len(spec_list) == 0:
        logger.info('No spec changed, so exit as failed. You must modify spec when add patch')
        sys.exit(1)

    rpm_release = []
    for spec in spec_list:
        logger.info('spec is ====== {0}'.format(spec))
        
        # get release
        cmd = "rpm -q --qf '%{{VERSION}}-%{{RELEASE}}\n' --specfile {0}".format(
            project_dir + '/' + spec)
        ret, out, err = shell_cmd(cmd)
        if ret != 0 and re.match(r'^error: Group ', err):
            with open(project_dir + '/' + spec, 'r') as my_f:
                tmpstr = my_f.read()
                tmpstr1 = re.sub(r'(%package|Name:)(.*)', r'\1\2\nGroup:xdf', tmpstr, re.M)
            a = tempfile.mktemp()
            with open(a, 'w') as b:
                b.write(tmpstr1)
                b.flush()
            cmd = "rpm -q --qf '%{{VERSION}}-%{{RELEASE}}\n' --specfile {0}".format(a)
            ret, out, err = shell_cmd(cmd)
            if ret != 0:
                print "run: %s : failed,the out is %s,the err is %s" % (cmd, out, err)
                out = 'read spec failed by: rpm -q --specfile'
            os.remove(a)
        elif ret != 0 and not re.match(r'^error: Group ', err):
            print "run: %s : failed,the out is %s,the err is %s" % (cmd, out, err)
            out = 'read spec failed by: rpm -q --specfile'
        rpm_release.append(out.split('\n')[0])

    # 切换到上一个提交点获取相关信息
    # 切换到对应的提交点
    cmd = 'cd {0};git checkout HEAD~1'.format(project_dir)
    ret, out, err = shell_cmd(cmd)
    if ret != 0:
        logger.error("run: %s : failed,the out is %s,the err is %s" % (cmd, out, err))
        sys.exit(1)
    
    rpm_release_old = []
    for spec in spec_list:
        logger.info('old spec is ====== {0}'.format(spec))
        # get src rpm
        cmd = "rpm -q --qf '%{{VERSION}}-%{{RELEASE}}\n' --specfile {0}".format(
            project_dir + '/' + spec)
        ret, out, err = shell_cmd(cmd)
        if ret != 0 and re.match(r'^error: Group ', err):
            with open(project_dir + '/' + spec, 'r') as my_f:
                tmpstr = my_f.read()
                tmpstr1 = re.sub(r'(%package|Name:)(.*)', r'\1\2\nGroup:xdf', tmpstr, re.M)
            a = tempfile.mktemp()
            with open(a, 'w') as b:
                b.write(tmpstr1)
                b.flush()
            cmd = "rpm -q --qf '%{{VERSION}}-%{{RELEASE}}\n' --specfile {0}".format(a)
            ret, out, err = shell_cmd(cmd)
            if ret != 0:
                print "run: %s : failed,the out is %s,the err is %s" % (cmd, out, err)
                out = 'read spec failed by: rpm -q --specfile'
            os.remove(a)
        elif ret != 0 and not re.match(r'^error: Group ', err):
            print "run: %s : failed,the out is %s,the err is %s" % (cmd, out, err)
            out = 'read spec failed by: rpm -q --specfile'
        rpm_release_old.append(out.split('\n')[0])
    
    # check spec version changed
    only_hw_release = True
    for i in range(0, len(rpm_release)):
        '''if rpm_release[i] <= rpm_release_old[i]:
            logger.error("new version-release({0}) is small/equal than the last version-release({1})".format(rpm_release[i], rpm_release_old[i]))
            sys.exit(1)'''
        logger.info("new: {0}  ###  old: {1}".format(rpm_release[i], rpm_release_old[i]))
        version_release = rpm_release[i].split('.h')[0]
        hw_release = rpm_release[i].split('.h')[1]
        version_release_old = rpm_release_old[i].split('.h')[0]
        hw_release_old = rpm_release_old[i].split('.h')[1]
        if version_release != version_release_old or hw_release <= hw_release_old:
            only_hw_release = False
            
    # hw release changed, so check the name of patch
    if only_hw_release:
        for patch in patch_list:
            if not re.match('euleros-(bugfix|cve|featrue|security|enhancement)-.*', patch) and not re.match('euleros-uvp-(bugfix|cve|featrue|security|enhancement)-.*', patch):
                logger.error("The patch: {0} is unconfirmed to the standards.\n please refer to:  http://3ms.huawei.com/hi/group/3078743/wiki_5161285.html".format(patch))
                sys.exit(1)
            else:
                logger.info("The patch: {0} is ok".format(patch))
    else:
        logger.info('hw release has no changes, so skip')
        return True
        

if __name__ == "__main__":
    project_dir = REPO_DIR + '/' + PROJECT.replace('\n', '')
    ret, out, err = shell_cmd('cd {0};git diff --name-status HEAD~1 HEAD~0'.format(project_dir))
    if ret != 0:
        print "run: %s : failed,the out is %s,the err is %s" % (COMMOND, out, err)
        sys.exit(1)
    patch_list = re.findall('A\s(.+\.patch)', out)
    if len(patch_list) == 0:
        logger.info('No patch changed, so exit as success')
        sys.exit(0)
    
    check_spec_for_patch(project_dir, patch_list)

